﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;

namespace Zero.UControl.Demo.Helper.PDF
{
    /// <summary>
    /// Xaml控件多页面导出工具类
    /// </summary>
    public static class MultiPagePdfExporter
    {
        public static void ExportVisualsToPdf(IEnumerable<Visual> visuals, string pdfPath, PdfExportOptions options)
        {
            if (visuals == null || string.IsNullOrWhiteSpace(pdfPath))
                throw new ArgumentException("参数不能为空");

            PdfDocument pdf = new PdfDocument();
            int pageNumber = 1;

            // A4 尺寸（point）: 1英寸 = 72 point, A4 = 8.27 x 11.69 英寸
            double A4PageWidth = 8.27 * 72;
            double A4PageHeight = 11.69 * 72;

            // 有效内容区域（去除页边距、页眉页脚）
            double contentWidth = A4PageWidth - 2 * options.Margin;
            double contentHeight = A4PageHeight - 2 * options.Margin - 50;

            double pxPerPoint = options.Dpi / 72.0;
            int blockHeightPx = (int)(contentHeight * pxPerPoint);

            foreach (var visual in visuals)
            {
                Rect bounds = VisualTreeHelper.GetDescendantBounds(visual); // 获取包含子容器内容的边界
                double scale = options.Dpi / 96.0;

                int pixelWidth = (int)(bounds.Width * scale);
                int pixelHeight = (int)(bounds.Height * scale);

                // 渲染整个 visual 为位图
                RenderTargetBitmap rtb = new RenderTargetBitmap(pixelWidth, pixelHeight, options.Dpi, options.Dpi, PixelFormats.Pbgra32);
                DrawingVisual dv = new DrawingVisual(); // 绘制整个可视化控件的容器
                using (DrawingContext ctx = dv.RenderOpen())
                {
                    VisualBrush vb = new VisualBrush(visual);
                    ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
                }
                rtb.Render(dv);

                // 单页情况 可视控件的像素高度小于单页A4内容区域的像素高度
                if (pixelHeight <= blockHeightPx)
                {
                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(rtb));
                    using MemoryStream stream = new MemoryStream();
                    encoder.Save(stream);
                    stream.Position = 0;

                    PdfPage page = pdf.AddPage();
                    page.Width = A4PageWidth;
                    page.Height = A4PageHeight;

                    XGraphics gfx = XGraphics.FromPdfPage(page);
                    XImage img = XImage.FromStream(stream);

                    // 从像素宽度转换为图像宽度
                    double imgDrawWidth = img.PixelWidth / pxPerPoint;
                    double imgDrawHeight = img.PixelHeight / pxPerPoint;
                    
                    double x = options.Margin;
                    double y = options.Margin + 16;

                    // 可选：垂直居中：y += (contentHeight - imgDrawHeight) / 2;

                    gfx.DrawImage(img, x, y, imgDrawWidth, imgDrawHeight);

                    DrawHeaderFooterWatermark(gfx, page, options, pageNumber);

                    pageNumber++;
                }
                else
                {
                    // 多页分页
                    int yOffset = 0;
                    while (yOffset < pixelHeight)
                    {
                        int currentBlockHeight = Math.Min(blockHeightPx, pixelHeight - yOffset);
                        // 根据像素宽度进行裁剪
                        Int32Rect sourceRect = new Int32Rect(0, yOffset, pixelWidth, currentBlockHeight);
                        var croppedBitmap = new CroppedBitmap(rtb, sourceRect);

                        PngBitmapEncoder encoder = new PngBitmapEncoder();
                        encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));
                        using MemoryStream stream = new MemoryStream();
                        encoder.Save(stream);
                        stream.Position = 0;

                        PdfPage page = pdf.AddPage();
                        page.Width = A4PageWidth;
                        page.Height = A4PageHeight;

                        XGraphics gfx = XGraphics.FromPdfPage(page);
                        XImage img = XImage.FromStream(stream);

                        double imgDrawWidth = img.PixelWidth / pxPerPoint;
                        double imgDrawHeight = img.PixelHeight / pxPerPoint;

                        double x = options.Margin;
                        double y = options.Margin + 16;

                        gfx.DrawImage(img, x, y, imgDrawWidth, imgDrawHeight);

                        DrawHeaderFooterWatermark(gfx, page, options, pageNumber);

                        pageNumber++;
                        yOffset += currentBlockHeight;
                    }
                }
            }

            pdf.Save(pdfPath);
        }

        /// <summary>
        /// 页眉、页脚、水印绘制封装
        /// </summary>
        private static void DrawHeaderFooterWatermark(XGraphics gfx, PdfPage page, PdfExportOptions options, int pageNumber)
        {
            double contentWidth = page.Width - 2 * options.Margin;

            // 页眉
            if (!string.IsNullOrEmpty(options.HeaderText))
            {
                double headerTopMargin = 10d;
                double lineTopMargin = 26d;
                double lineHeight = 20d;

                gfx.DrawString(options.HeaderText, options.Font, options.Brush,
                    new XRect(options.Margin, headerTopMargin, contentWidth, lineHeight), XStringFormats.TopLeft);

                gfx.DrawLine(new XPen(XColors.Black, 1d),
                    new XPoint(options.Margin, lineTopMargin),
                    new XPoint(page.Width - options.Margin, lineTopMargin));
            }

            // 页脚
            if (!string.IsNullOrEmpty(options.FooterText))
            {
                string footer = options.FooterText.Replace("{page}", pageNumber.ToString());
                gfx.DrawString(footer, options.Font, options.Brush,
                    new XRect(0, page.Height - 40, page.Width - 20, 20), XStringFormats.CenterRight);
            }

            // 水印
            if (!string.IsNullOrEmpty(options.WatermarkText))
            {
                var font = new XFont(options.Font.Name2, 40d, XFontStyleEx.BoldItalic);
                var brush = new XSolidBrush(XColor.FromArgb(40, 0, 0, 0));

                gfx.TranslateTransform(page.Width / 2, page.Height / 2);
                gfx.RotateTransform(-45);
                gfx.DrawString(options.WatermarkText, font, brush,
                    new XRect(-300, -20, 600, 40), XStringFormats.Center);
                gfx.RotateTransform(45);
                gfx.TranslateTransform(-page.Width / 2, -page.Height / 2);
            }
        }

    }
}
